package org.example.user.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.common.config.BusinessException;
import org.example.user.dto.AssignAclDTO;
import org.example.user.dto.CreateAclDTO;
import org.example.user.dto.UpdateAclDTO;
import org.example.user.dto.AclQueryDTO;
import org.example.user.entity.SysAclEntity;
import org.example.user.entity.SysMenuEntity;
import org.example.user.entity.SysRoleAclEntity;
import org.example.user.mapper.SysAclMapper;
import org.example.user.mapper.SysMenuMapper;
import org.example.user.service.ISysAclService;
import org.example.user.vo.SysAclVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mybatisflex.spring.service.impl.ServiceImpl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 权限表 服务层实现。
 *
 * @author mybatis-flex-helper automatic generation
 * @since 1.0
 */
@Slf4j
@Service
public class SysAclServiceImpl extends ServiceImpl<SysAclMapper, SysAclEntity> implements ISysAclService {

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Transactional
    @Override
    public int createAcl(CreateAclDTO createAclDTO) {
        SysAclEntity sysAclEntity = new SysAclEntity();
        BeanUtils.copyProperties(createAclDTO, sysAclEntity);
        sysAclEntity.setIsDelete(0);
        sysAclEntity.setCreatedBy("admin");
        sysAclEntity.setCreatedTime(new Date());
        sysAclMapper.insert(sysAclEntity);

        if (createAclDTO.getMenuId() != null) {
            SysMenuEntity sysMenuEntity = new SysMenuEntity();
            sysMenuEntity.setId(createAclDTO.getMenuId());
            sysMenuEntity.setAclId(sysAclEntity.getId());
            sysMenuMapper.update(sysMenuEntity);
        }

        return 1;
    }

    @Override
    public int updateAcl(UpdateAclDTO updateAclDTO) {
        SysAclEntity sysAclEntity = sysAclMapper.selectOneById(updateAclDTO.getAclId());
        if (sysAclEntity == null) {
            throw new BusinessException("权限点不存在");
        }
        BeanUtils.copyProperties(updateAclDTO, sysAclEntity);
        sysAclMapper.update(sysAclEntity);

        if (updateAclDTO.getMenuId() != null) {
            SysMenuEntity sysMenuEntity = new SysMenuEntity();
            sysMenuEntity.setId(updateAclDTO.getMenuId());
            sysMenuEntity.setAclId(sysAclEntity.getId());
            sysMenuMapper.update(sysMenuEntity);
        }

        return 1;
    }

    @Override
    public int deleteAcl(Long aclId) {
        SysAclEntity sysAclEntity = sysAclMapper.selectOneById(aclId);
        if (sysAclEntity == null) {
            throw new BusinessException("权限点不存在");
        }
        sysAclMapper.delete(sysAclEntity);
        log.info("删除权限，aclId: {}", aclId);
        return 1;
    }

    @Override
    public Page<SysAclVO> pageList(AclQueryDTO aclQueryDTO) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (!StringUtils.isEmpty(aclQueryDTO.getName())) {
            queryWrapper.like(SysAclEntity::getName, aclQueryDTO.getName());
        }
        if (!StringUtils.isEmpty(aclQueryDTO.getCode())) {
            queryWrapper.like(SysAclEntity::getCode, aclQueryDTO.getCode());
        }

        Page<SysAclEntity> paginate = sysAclMapper.paginate(aclQueryDTO.getPage(), aclQueryDTO.getSize(), queryWrapper);

        List<SysAclEntity> records = paginate.getRecords();
        List<SysAclVO> aclVOS = records.stream().map(this::convertToVO).collect(Collectors.toList());

        Page<SysAclVO> page = new Page<>();
        page.setRecords(aclVOS);
        page.setTotalRow(paginate.getTotalRow());
        page.setTotalPage(paginate.getTotalPage());
        page.setPageNumber(paginate.getPageNumber());
        page.setPageSize(paginate.getPageSize());

        return page;
    }

    private SysAclVO convertToVO(SysAclEntity entity) {
        SysAclVO vo = new SysAclVO();
        BeanUtils.copyProperties(entity, vo);

        // 查询关联的菜单信息
        if (entity.getId() != null) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("acl_id", entity.getId());
            SysMenuEntity sysMenuEntity = sysMenuMapper.selectOneByQuery(queryWrapper);
            if (sysMenuEntity != null) {
                vo.setMenuId(sysMenuEntity.getId());
                vo.setMenuName(sysMenuEntity.getName());
            }
        }
        return vo;
    }

    @Override
    public SysAclVO getAclDetail(Long aclId) {
        SysAclEntity sysAclEntity = sysAclMapper.selectOneById(aclId);
        if (sysAclEntity == null) {
            throw new BusinessException("权限点不存在");
        }
        return convertToVO(sysAclEntity);
    }

    @Override
    public List<SysAclVO> getAclTree() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(SysAclEntity::getIsDelete, 0);
        List<SysAclEntity> sysAclEntities = sysAclMapper.selectListByQuery(queryWrapper);
        List<SysAclVO> aclVOS = sysAclEntities.stream().map(this::convertToVO).collect(Collectors.toList());

        // 构建树形结构
        return buildAclTree(aclVOS);
    }

    private List<SysAclVO> buildAclTree(List<SysAclVO> aclVOS) {
        // 找到所有顶级节点（parentId为null或0）
        List<SysAclVO> rootNodes = aclVOS.stream()
                .filter(acl -> acl.getParentId() == null || acl.getParentId() == 0)
                .collect(Collectors.toList());

        // 为每个顶级节点找到子节点
        rootNodes.forEach(root -> findChildren(root, aclVOS));

        return rootNodes;
    }

    private void findChildren(SysAclVO parent, List<SysAclVO> allNodes) {
        List<SysAclVO> children = allNodes.stream()
                .filter(node -> Objects.equals(node.getParentId(), parent.getId()))
                .collect(Collectors.toList());

        parent.setChildren(children);
        children.forEach(child -> findChildren(child, allNodes)); // 递归处理子节点
    }

    @Override
    public int linkMenu(Long aclId, Long menuId) {
        SysMenuEntity sysMenuEntity = new SysMenuEntity();
        sysMenuEntity.setId(menuId);
        sysMenuEntity.setAclId(aclId);
        sysMenuMapper.update(sysMenuEntity);
        return 1;
    }
}
